#include "sche_mgr.h"
#include "sche.h"
#include "fix_sche.h"
#include "list.h"
#include <malloc.h>
#include <string.h>
#include <assert.h>

C_CODE_BEGIN

struct sche_mgr {
	struct list* creator;
};

struct sche_ele {
	sche_creator cr;
	const char* name;
};

EXPORT_FUNC struct sche_mgr* sche_mgr_create() {
	struct sche_mgr* mg = malloc( sizeof(struct sche_mgr) );
	mg->creator = list_create( sizeof( struct sche_ele ) , 4 );
	_fix_sche_register(mg);
	return mg;
}


static void _free_foreach( void*obj,void* par ) {
	free( (void*)(((struct sche_ele*)(obj))->name) );
}



EXPORT_FUNC void sche_mgr_destroy( struct sche_mgr*  mgr ) {
	list_foreach( mgr->creator , _free_foreach , NULL);
	list_destroy( mgr->creator );
	free(mgr);
}


struct find {
	const char* name;
	sche_creator cr;
};

static bool _sc_find( void* obj , void* par ) {
	struct find* f = (struct find*)par;
	struct sche_ele* sele = (struct sche_ele*)obj;
	if( strcmp(f->name,sele->name) == 0 ) {
		f->cr = sele->cr;
		return false;
	}

	return true;
}

EXPORT_FUNC struct sche* sche_mgr_spawn_sche
	( struct sche_mgr* smgr,const char* sche_type , 
	const char* worker_tpye , struct worker_mgr* wmgr , size_t thread_size ) {
		struct find f;
		f.name = sche_type;
		f.cr = NULL;
		list_until( smgr->creator , _sc_find , &f );
		return f.cr == NULL ? NULL : f.cr( thread_size , wmgr , worker_tpye );
}

#ifndef NDEBUG

static bool _check_until( void* obj , void* par ) {
	struct sche_ele* e = (struct sche_ele*)obj;
	struct find* f = ( struct find* )par;
	if( strcmp( e->name ,  f->name ) ==0 ) {
		f->cr = e->cr;
		return false;
	}
	return true;
}

static bool _check_name_valid( struct sche_mgr* mgr ,const char* n ) {
	struct find f;
	f.name = n;
	f.cr= NULL;
	list_until( mgr->creator ,_check_until ,&f );
	return f.cr == NULL;
}

#endif 

EXPORT_FUNC void sche_mgr_register( struct sche_mgr* mgr, const char* na, sche_creator cr ) {
	struct sche_ele ele ;
	size_t len ;
	assert( _check_name_valid(mgr,na) );
	len = strlen(na);
	ele.name = malloc( sizeof(char)*(len+1) );
	strcpy( (char*)ele.name , na );
	ele.cr = cr;
	list_push_back( mgr->creator , &ele );
}


C_CODE_END